home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / RCS_56.ARJ / RCSCLEAN.C < prev    next >
C/C++ Source or Header  |  1992-02-11  |  6KB  |  298 lines

  1. /* rcsclean - clean up working files */
  2.  
  3. /* Copyright 1991 by Paul Eggert
  4.    Distributed under license by the Free Software Foundation, Inc.
  5.  
  6. This file is part of RCS.
  7.  
  8. RCS is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2, or (at your option)
  11. any later version.
  12.  
  13. RCS is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with RCS; see the file COPYING.  If not, write to
  20. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. Report problems and direct all questions to:
  23.  
  24.     rcs-bugs@cs.purdue.edu
  25.  
  26. */
  27.  
  28. #include "rcsbase.h"
  29.  
  30. #if has_dirent
  31.     static int get_directory P((char const*,char***));
  32. #endif
  33.  
  34. static int unlock P((struct hshentry *));
  35. static void cleanup P((void));
  36.  
  37. static RILE *workptr;
  38. static int exitstatus;
  39.  
  40. mainProg(rcscleanId, "rcsclean", "$Id: rcsclean.c,v 5.1 1991/11/03 01:11:44 eggert Exp $")
  41. {
  42.     static char const usage[] =
  43.         "\nrcsclean: usage: rcsclean [-ksubst] [-{nqru}[rev]] [-Vn] [-xsuffixes] [file ...]";
  44.  
  45.     static struct buf revision;
  46.  
  47.     char *a, **newargv;
  48.     char const *rev, *p;
  49.     int changelock, expmode, perform, unlocked, unlockflag, waslocked;
  50.     struct hshentries *deltas;
  51.     struct hshentry *delta;
  52.     struct stat workstat;
  53.  
  54.     setrid();
  55.  
  56.     expmode = -1;
  57.     rev = nil;
  58.     suffixes = X_DEFAULT;
  59.     perform = true;
  60.     unlockflag = false;
  61.  
  62.     argc = getRCSINIT(argc, argv, &newargv);
  63.     argv = newargv;
  64.     for (;;) {
  65.         if (--argc <= 0) {
  66. #            if has_dirent
  67.                 argc = get_directory(".", &newargv);
  68.                 argv = newargv;
  69.                 break;
  70. #            else
  71.                 faterror("no file names specified");
  72. #            endif
  73.         }
  74.         a = *++argv;
  75.         if (*a++ != '-')
  76.             break;
  77.         switch (*a++) {
  78.             case 'k':
  79.                 if (0 <= expmode)
  80.                     redefined('k');
  81.                 if ((expmode = str2expmode(a))  <  0)
  82.                     goto unknown;
  83.                 break;
  84.  
  85.             case 'n':
  86.                 perform = false;
  87.                 goto handle_revision;
  88.  
  89.             case 'q':
  90.                 quietflag = true;
  91.                 /* fall into */
  92.             case 'r':
  93.             handle_revision:
  94.                 if (*a) {
  95.                     if (rev)
  96.                         warn("redefinition of revision number");
  97.                     rev = a;
  98.                 }
  99.                 break;
  100.  
  101.             case 'u':
  102.                 unlockflag = true;
  103.                 goto handle_revision;
  104.  
  105.             case 'V':
  106.                 setRCSversion(*argv);
  107.                 break;
  108.  
  109.             case 'x':
  110.                 suffixes = a;
  111.                 break;
  112.  
  113.             default:
  114.             unknown:
  115.                 faterror("unknown option: %s%s", *argv, usage);
  116.         }
  117.     }
  118.  
  119.     do {
  120.         ffree();
  121.  
  122.         if (!(
  123.             0 < pairfilenames(
  124.                 argc, argv,
  125.                 unlockflag&perform ? rcswriteopen : rcsreadopen,
  126.                 true, true
  127.             ) &&
  128.             (workptr = Iopen(workfilename,FOPEN_R_WORK,&workstat))
  129.         ))
  130.             continue;
  131.  
  132.         gettree();
  133.  
  134.         p = 0;
  135.         if (rev) {
  136.             if (!fexpandsym(rev, &revision, workptr))
  137.                 continue;
  138.             p = revision.string;
  139.         } else if (Head)
  140.             switch (unlockflag ? findlock(false,&delta) : 0) {
  141.                 default:
  142.                     continue;
  143.                 case 0:
  144.                     p = Dbranch ? Dbranch : "";
  145.                     break;
  146.                 case 1:
  147.                     p = delta->num;
  148.                     break;
  149.             }
  150.         delta = 0;
  151.         deltas = 0;  /* Keep lint happy.  */
  152.         if (p  &&  !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
  153.             continue;
  154.  
  155.         waslocked = delta && delta->lockedby;
  156.         locker_expansion = unlock(delta);
  157.         unlocked = locker_expansion & unlockflag;
  158.         changelock = unlocked & perform;
  159.         if (unlocked<waslocked  &&  workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
  160.             continue;
  161.  
  162.         if (!dorewrite(unlockflag, changelock))
  163.             continue;
  164.  
  165.         if (0 <= expmode)
  166.             Expand = expmode;
  167.         else if (
  168.             waslocked  &&
  169.             Expand == KEYVAL_EXPAND  &&
  170.             WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
  171.         )
  172.             Expand = KEYVALLOCK_EXPAND;
  173.  
  174.         getdesc(false);
  175.  
  176.         if (
  177.             !delta ? workstat.st_size!=0 :
  178.             0 < rcsfcmp(
  179.                 workptr, &workstat,
  180.                 buildrevision(deltas, delta, (FILE*)0, false),
  181.                 delta
  182.             )
  183.         )
  184.             continue;
  185.  
  186.         if (quietflag < unlocked)
  187.             aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSfilename);
  188.  
  189.         if_advise_access(changelock  &&  deltas->first != delta,
  190.             finptr, MADV_SEQUENTIAL
  191.         );
  192.         if (!donerewrite(changelock))
  193.             continue;
  194.  
  195.         if (!quietflag)
  196.             aprintf(stdout, "rm -f %s\n", workfilename);
  197.         Izclose(&workptr);
  198.         if (perform  &&  un_link(workfilename) != 0)
  199.             eerror(workfilename);
  200.  
  201.     } while (cleanup(),  ++argv,  0 < --argc);
  202.  
  203.     tempunlink();
  204.     if (!quietflag)
  205.         Ofclose(stdout);
  206.     exitmain(exitstatus);
  207. }
  208.  
  209.     static void
  210. cleanup()
  211. {
  212.     if (nerror) exitstatus = EXIT_FAILURE;
  213.     Izclose(&finptr);
  214.     Izclose(&workptr);
  215.     Ozclose(&fcopy);
  216.     Ozclose(&frewrite);
  217.     dirtempunlink();
  218. }
  219.  
  220. #if lint
  221. #       define exiterr rcscleanExit
  222. #endif
  223.     exiting void
  224. exiterr()
  225. {
  226.     dirtempunlink();
  227.     tempunlink();
  228.     _exit(EXIT_FAILURE);
  229. }
  230.  
  231.     static int
  232. unlock(delta)
  233.     struct hshentry *delta;
  234. {
  235.     register struct lock **al, *l;
  236.  
  237.     if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
  238.         for (al = &Locks;  (l = *al);  al = &l->nextlock)
  239.             if (l->delta == delta) {
  240.                 *al = l->nextlock;
  241.                 delta->lockedby = 0;
  242.                 return true;
  243.             }
  244.     return false;
  245. }
  246.  
  247. #if has_dirent
  248.     static int
  249. get_directory(dirname, aargv)
  250.     char const *dirname;
  251.     char ***aargv;
  252. /*
  253.  * Put a vector of all DIRNAME's directory entries names into *AARGV.
  254.  * Ignore names of RCS files.
  255.  * Yield the number of entries found.  Terminate the vector with 0.
  256.  * Allocate the storage for the vector and entry names.
  257.  * Do not sort the names.  Do not include '.' and '..'.
  258.  */
  259. {
  260.     int i, entries = 0, entries_max = 64;
  261.     size_t chars = 0, chars_max = 1024;
  262.     size_t *offset = tnalloc(size_t, entries_max);
  263.     char *a = tnalloc(char, chars_max), **p;
  264.     DIR *d;
  265.     struct dirent *e;
  266.  
  267.     if (!(d = opendir(dirname)))
  268.         efaterror(dirname);
  269.     while ((errno = 0,  e = readdir(d))) {
  270.         char const *en = e->d_name;
  271.         size_t s = strlen(en) + 1;
  272.         if (en[0]=='.'   &&   (!en[1]  ||  en[1]=='.' && !en[2]))
  273.             continue;
  274.         if (rcssuffix(en))
  275.             continue;
  276.         while (chars_max < s + chars)
  277.             a = trealloc(char, a, chars_max<<=1);
  278.         if (entries == entries_max)
  279.             offset = trealloc(size_t, offset, entries_max<<=1);
  280.         offset[entries++] = chars;
  281.         VOID strcpy(a+chars, en);
  282.         chars += s;
  283.     }
  284.     if (errno  ||  closedir(d) != 0)
  285.         efaterror(dirname);
  286.     if (chars)
  287.         a = trealloc(char, a, chars);
  288.     else
  289.         tfree(a);
  290.     *aargv = p = tnalloc(char*, entries+1);
  291.     for (i=0; i<entries; i++)
  292.         *p++ = a + offset[i];
  293.     *p = 0;
  294.     tfree(offset);
  295.     return entries;
  296. }
  297. #endif
  298.